//
//  CAIPhotoAuthorizationManager.m
//  CollagePicture
//
//  Created by simon on 2021/11/9.
//  Copyright © 2021 zxm. All rights reserved.
//

#import "CAIPhotoAuthorizationManager.h"
@import Photos;

@interface CAIPhotoAuthorizationManager ()

@property (nonatomic, copy) NSString *appDisplayName;

@end

@implementation CAIPhotoAuthorizationManager



+ (instancetype)shareInstance
{
    static id instance = nil;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (instancetype)init
{
    if (self = [super init])
    {
        NSDictionary *infoDict = [NSBundle mainBundle].localizedInfoDictionary;
        if (!infoDict||infoDict.count == 0) {
            infoDict = [NSBundle mainBundle].infoDictionary;
        }
        NSString *appName = [infoDict valueForKey:@"CFBundleDisplayName"];
        if (!appName){
            appName = [infoDict valueForKey:@"CFBundleName"];
        }
        _appDisplayName = appName;
    }
    return self;
}

#pragma mark - 相册授权

+ (void)requestPhotoLibraryAuthorization:(void(^)(ZXPhotoAuthorizationStatus status))callback
{
    [[self alloc] requestPhotoLibraryAuthorizationWithDeniedAlertViewInViewController:nil call:callback];
}

- (void)requestPhotoLibraryAuthorizationWithDeniedAlertViewInViewController:(nullable UIViewController *)sourceController call:(void(^)(ZXPhotoAuthorizationStatus status))callback
{
    if (@available(iOS 14, *)) {
        PHAccessLevel level = PHAccessLevelReadWrite;
        PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatusForAccessLevel:level];
        switch (authStatus) {
            case PHAuthorizationStatusDenied:
            case PHAuthorizationStatusRestricted:
            {
                [self presentAuthorizationStatusDeniedAlertViewInViewController:sourceController authorizationType:ZXPhotoAuthorizationTypePhotoLibrary];

                [self executeCallback:callback status:authStatus == PHAuthorizationStatusDenied ? ZXPhotoAuthorizationStatusDenied:ZXPhotoAuthorizationStatusRestricted];
            }
                break;
            case PHAuthorizationStatusNotDetermined:
            {
                [PHPhotoLibrary requestAuthorizationForAccessLevel:level handler:^(PHAuthorizationStatus status) {

                    dispatch_async(dispatch_get_main_queue(), ^{

                        switch (status) {
                            case PHAuthorizationStatusAuthorized:
                                [self executeCallback:callback status:ZXPhotoAuthorizationStatusAuthorized];
                                break;
                            case PHAuthorizationStatusDenied:
                            case PHAuthorizationStatusRestricted:{
                                [self executeCallback:callback status:ZXPhotoAuthorizationStatusAlertDeniedOrRestricted];
                            }
                                break;
                            default:
                                break;
                        }
                    });
                }];
            }
                break;
            case PHAuthorizationStatusLimited:
//                [self executeCallback:callback status:ZXPhotoAuthorizationStatusAuthorized];
                break;
            default: [self executeCallback:callback status:ZXPhotoAuthorizationStatusAuthorized];
                break;
        }

    } else {
        PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
        if (authStatus == PHAuthorizationStatusDenied || authStatus == PHAuthorizationStatusRestricted)
        {
            [self presentAuthorizationStatusDeniedAlertViewInViewController:sourceController authorizationType:ZXPhotoAuthorizationTypePhotoLibrary];

            [self executeCallback:callback status:authStatus == PHAuthorizationStatusDenied ? ZXPhotoAuthorizationStatusDenied:ZXPhotoAuthorizationStatusRestricted];
        }
        else if (authStatus == PHAuthorizationStatusNotDetermined)
        {
            //点击之后警告框会消失；异步+新的队列执行；
            [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    
                    if (status == PHAuthorizationStatusAuthorized) {
                        [self executeCallback:callback status:ZXPhotoAuthorizationStatusAuthorized];
                        
                    } else if (status == PHAuthorizationStatusDenied || status == PHAuthorizationStatusRestricted)
                    {
                        [self executeCallback:callback status:ZXPhotoAuthorizationStatusAlertDeniedOrRestricted];
                    }
                });
            }];
        }
        else
        {
            [self executeCallback:callback status:ZXPhotoAuthorizationStatusAuthorized];
        }
    }
}

#pragma mark - 摄像头授权

+ (void)requestCameraAuthorization:(void(^)(ZXPhotoAuthorizationStatus status))callback
{
    [[self alloc]requestCameraAuthorizationWithDeniedAlertViewInViewController:nil call:callback];
}

- (void)requestCameraAuthorizationWithDeniedAlertViewInViewController:(nullable UIViewController *)sourceController call:(void(^)(ZXPhotoAuthorizationStatus status))callback
{
    // 判断是否支持摄像头
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
    {
        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        if (authStatus == AVAuthorizationStatusDenied || authStatus == AVAuthorizationStatusRestricted)
        {
            [self presentAuthorizationStatusDeniedAlertViewInViewController:sourceController authorizationType:ZXPhotoAuthorizationTypeAVCaptureCamera];
            [self executeCallback:callback status:authStatus == AVAuthorizationStatusDenied ? ZXPhotoAuthorizationStatusDenied:ZXPhotoAuthorizationStatusRestricted];
        }
        else if (authStatus == AVAuthorizationStatusNotDetermined)
        {
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (granted){
                        [self executeCallback:callback status:ZXPhotoAuthorizationStatusAuthorized];
                    }
                    else{
                        [self executeCallback:callback status:ZXPhotoAuthorizationStatusAlertDeniedOrRestricted];
                    }
                });
            }];
        }
        else
        {
            [self executeCallback:callback status:ZXPhotoAuthorizationStatusAuthorized];
        }
    }
    else
    {
        [self executeCallback:callback status:ZXPhotoAuthorizationStatusNotSupport];
        //模拟器
        [self presentGeneralAlertInViewController:sourceController withTitle:@"该设备不支持摄像头拍照" message:nil cancelButtonTitle:nil cancleHandler:nil doButtonTitle:@"确定" doHandler:nil];
    }
}

#pragma mark - callback

- (void)executeCallback:(void (^)(ZXPhotoAuthorizationStatus))callback status:(ZXPhotoAuthorizationStatus)status {
    if (callback) {
        callback(status);
    }
}


#pragma mark - DeniedAlertView

- (void)presentAuthorizationStatusDeniedAlertViewInViewController:(nullable UIViewController *)sourceController authorizationType:(ZXPhotoAuthorizationType)type
{
    if ([self.delegate respondsToSelector:@selector(showAlertViewWithPhotoAuthorizationManager:authorizationType:)])
    {
        [self.delegate showAlertViewWithPhotoAuthorizationManager:self authorizationType:type];
    }
    else
    {
        if (!sourceController)
        {
            return;
        }
        NSString *title = nil;
        if (type == ZXPhotoAuthorizationTypePhotoLibrary)
        {
            title =[NSString stringWithFormat:@"请在iPhone的\"设置-隐私-照片\"选项中，\r允许%@访问你的手机照片",self.appDisplayName];
        }
        else if (type == ZXPhotoAuthorizationTypeAVCaptureCamera)
        {
            title =[NSString stringWithFormat:@"请在iPhone的\"设置-隐私-相机\"选项中，\r允许%@访问你的手机相机",self.appDisplayName];
        }
        [self presentGeneralAlertInViewController:sourceController withTitle:title message:nil cancelButtonTitle:@"取消" cancleHandler:nil doButtonTitle:@"去设置" doHandler:^(UIAlertAction *action) {
            
//            如果指定的URL scheme由另一个app应用程序处理，options可以使用通用链接的key。空的options字典与旧的openURL调用是相同的；
//            当openURL:options:completionHandler:方法的选项字典中有这个key时，如果设置为YES, 则URL必须是通用链接，并且有一个已安装的应用程序被用于打开该URL时，当前app才会打开URL。
//            如果没有其它app应用程序配置这个通用链接，或者用户设置NO禁用打开链接，则completion handler 回调里的success为false(NO);
            NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
            if (@available(iOS 10.0,*)) {
                [[UIApplication sharedApplication]openURL:url options:@{} completionHandler:nil];
            }
            else
            {
                [[UIApplication sharedApplication] openURL:url];
            }
        }];
    }
}

#pragma mark - 弹框

- (void)presentGeneralAlertInViewController:(UIViewController *)viewController
                                  withTitle:(nullable NSString *)title
                                    message:(nullable NSString *)message
                          cancelButtonTitle:(nullable NSString *)cancelButtonTitle cancleHandler:(void (^ __nullable)(UIAlertAction *action))handler
                              doButtonTitle:(nullable NSString *)doButtonTitle
                                  doHandler:(void (^ __nullable)(UIAlertAction *action))doHandler
{
    if (!title && message) {
        title = @"";
    }
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    if (cancelButtonTitle.length >0)
    {
        //UIAlertAction的title参数不能为nil，会奔溃；
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(cancelButtonTitle, @"Cancel") style:UIAlertActionStyleCancel handler:handler];
        [alertController addAction:cancelAction];
    }
    if (doButtonTitle.length>0)
    {
        UIAlertAction *doAction = [UIAlertAction actionWithTitle:NSLocalizedString(doButtonTitle, @"OK") style:UIAlertActionStyleDefault handler:doHandler];
        [alertController addAction:doAction];
    }
    [viewController presentViewController:alertController animated:YES completion:nil];
}


@end


